package com.example.demo.service.impl;

import com.example.demo.entity.dto.ApiTestCaseResultDto;
import com.example.demo.enums.ProcessorEnum;
import com.example.demo.mapper.*;
import com.example.demo.entity.*;
import com.example.demo.entity.apiModel.GetExtractions;
import com.example.demo.entity.request.apiTestCaseStepReq.ApiTestCaseStepReq;
import com.example.demo.entity.request.apiTestCaseStepReq.UpdateApiTestCaseStepsReq;
import com.example.demo.entity.response.apiTestCaseStepResp.ApiTestCaseStepPageResp;
import com.example.demo.entity.testData.PageParams;
import com.example.demo.service.ApiService;
import com.example.demo.service.ApiTestCaseStepService;
import com.example.demo.service.DBConnectionService;
import com.example.demo.utils.DateToStamp;
import com.example.demo.utils.GroovyUtils;
import com.example.demo.utils.PageInfoNew;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ApiTestCaseStepServiceImpl implements ApiTestCaseStepService {

    @Resource
    ApiTestCaseStepMapper apiTestCaseStepMapper;

    @Resource
    ApiTestCaseMapper apiTestCaseMapper;

    @Resource
    TestCaseProcessorMapper testCaseProcessorMapper;

    @Resource
    ApiService apiService;

    @Resource
    DBConnectionService dbConnectionService;

    @Override
    public int insertStepToTestCase(List<ApiTestCaseStepReq> insertApiTestCaseStepReqs) {
        //根据testCaseId获取step总数
        int sortIndex = apiTestCaseStepMapper.findByTestCaseId(insertApiTestCaseStepReqs.get(0).getTestCaseId()).size();
        for (ApiTestCaseStepReq insertApiTestCaseStepReq : insertApiTestCaseStepReqs) {
            sortIndex += 1;
            insertApiTestCaseStepReq.setSort(sortIndex);
            if (null != insertApiTestCaseStepReq.getTestCaseProcessors() && insertApiTestCaseStepReq.getTestCaseProcessors().size() > 0) {
                for (TestCaseProcessor testCaseProcessor : insertApiTestCaseStepReq.getTestCaseProcessors()) {
                    testCaseProcessorMapper.insert(testCaseProcessor);
                }

            }
            apiTestCaseStepMapper.insertApiTestCaseStep(insertApiTestCaseStepReq);
        }
        return 1;
    }

    @Override
    public ApiTestCaseResultDto runStep(Integer testCaseId, Integer envId) {
        List<ApiTestCaseStep> apiTestCaseSteps = apiTestCaseStepMapper.findByTestCaseId(testCaseId);
        ApiTestCase apiTestCase = apiTestCaseMapper.findById(testCaseId);
        ApiTestCaseResult apiTestCaseResult = new ApiTestCaseResult();
        int pass = 0;
        int failed = 0;
        int count = 0;
        List<ApiRequestResult> apiRequestResults = new ArrayList<>();
        List<GetExtractions> getExtractionsList = new ArrayList<>();
        ApiTestCaseResultDto apiTestCaseResultDto = new ApiTestCaseResultDto();
        int startTime = (int) System.currentTimeMillis();
        for (ApiTestCaseStep apiTestCaseStep : apiTestCaseSteps) {
            log.info("获取测试用例步骤:" + apiTestCaseStep.toString());
            Api api = new Api();
            BeanUtils.copyProperties(apiTestCaseStep, api);
            api.setEnvId(envId);
            api.setProjectId(apiTestCase.getProjectId());
            List<TestCaseProcessor> testCaseProcessors = testCaseProcessorMapper.selectByStepId(apiTestCaseStep.getId());
            testCaseProcessor(testCaseProcessors, ProcessorEnum.PRE_PROCESSOR_TYPE);
            ApiRequestResult apiRequestResult = apiService.requestTestRun(api, getExtractionsList);
            testCaseProcessor(testCaseProcessors, ProcessorEnum.POST_PROCESSORS_TYPE);
            apiRequestResult.setApiId(apiTestCaseStep.getApiId());
            apiRequestResult.setApiTestCaseId(apiTestCaseStep.getTestCaseId());
            apiRequestResult.setApiTestCaseStepId(apiTestCaseStep.getId());
            if (apiRequestResult.getResultExtractions() != null) {
                getExtractionsList.addAll(apiRequestResult.getResultExtractions());
            }
            apiRequestResults.add(apiRequestResult);
//            apiRequestResultMapper.insertApiRequestResult(apiRequestResult);
            count += 1;
            if (apiRequestResult.getResultIsPass()) {
                pass += 1;
            } else {
                failed += 1;
            }
        }
        log.info("获取测试用例结果集:" + apiRequestResults);
        int endTime = (int) System.currentTimeMillis();
        apiTestCaseResult.setTestCaseId(testCaseId);
        apiTestCaseResult.setTestCaseName(apiTestCase.getName());
        apiTestCaseResult.setCountResults(count);
        apiTestCaseResult.setPassResults(pass);
        apiTestCaseResult.setFailedResults(failed);
        apiTestCaseResult.setCreateTime(DateToStamp.getTimeStamp());
        apiTestCaseResult.setUpdateTime(DateToStamp.getTimeStamp());
        apiTestCaseResult.setTestRunTime(endTime - startTime);
//        apiTestCaseResultMapper.insertResult(apiTestCaseResult);
        apiTestCaseResultDto.setApiRequestResults(apiRequestResults);
        apiTestCaseResultDto.setApiTestCaseResult(apiTestCaseResult);
        apiTestCaseResultDto.setCaseName(apiTestCase.getName());
        return apiTestCaseResultDto;
    }

    @Override
    public void apiTestCaseStepsEdit(UpdateApiTestCaseStepsReq updateApiTestCaseStepReq) {
        List<ApiTestCaseStepReq> apiTestCaseStepList = updateApiTestCaseStepReq.getApiTestCaseStepReqs();
        ApiTestCase apiTestCase = new ApiTestCase();
        apiTestCase.setUpdateTime(DateToStamp.getTimeStamp());
        apiTestCase.setEnvId(updateApiTestCaseStepReq.getEnvId());
        apiTestCase.setId(apiTestCaseStepList.get(0).getTestCaseId());
        apiTestCaseMapper.updateApiTestCase(apiTestCase);
        int sortIndex = 0;
        //更新步骤顺序
        for (ApiTestCaseStepReq apiTestCaseStepReq : apiTestCaseStepList) {
            sortIndex += 1;
            apiTestCaseStepReq.setSort(sortIndex);
            apiTestCaseStepReq.setUpdateTime(DateToStamp.getTimeStamp());
            apiTestCaseStepMapper.updateApiTestCaseStep(apiTestCaseStepReq);
//            if (apiTestCaseStepReq.getTestCaseProcessors() != null && !apiTestCaseStepReq.getTestCaseProcessors().isEmpty()) {
//                apiTestCaseStepReq.getTestCaseProcessors().forEach(testCaseProcessor -> {
//                    testCaseProcessor.setCreateTime(DateToStamp.getTimeStap());
//                    testCaseProcessor.setUpdateTime(DateToStamp.getTimeStap());
//                    testCaseProcessorMapper.insert(testCaseProcessor);
//                });
//            }

        }
    }

    @Override
    public void updateStepById(ApiTestCaseStepReq apiTestCaseStepReq) {
        apiTestCaseStepMapper.updateApiTestCaseStep(apiTestCaseStepReq);
        if (apiTestCaseStepReq.getTestCaseProcessors() != null && !apiTestCaseStepReq.getTestCaseProcessors().isEmpty()) {
            apiTestCaseStepReq.getTestCaseProcessors().forEach(testCaseProcessor -> {
                testCaseProcessor.setCreateTime(DateToStamp.getTimeStamp());
                testCaseProcessor.setUpdateTime(DateToStamp.getTimeStamp());
                testCaseProcessorMapper.insert(testCaseProcessor);
            });
        }
    }

    @Override
    public void apiTestCaseStepDelete(int StepId) {
        apiTestCaseStepMapper.deleteStepByStepId(StepId);
    }

    @Override
    public void apiTestCaseStepsDelete(List<Integer> ids) {
        if (!ids.isEmpty()) {
            for (int id : ids) {
                apiTestCaseStepMapper.deleteStepByStepId(id);
            }
        }
    }

    @Override
    public PageInfoNew<ApiTestCaseStepPageResp> findTestCaseStepPageByTestCaseId(int pageNum, int pageSize, int testCaseId) {
        PageHelper.startPage(pageNum, pageSize);
        List<ApiTestCaseStepPageResp> apiTestCaseStepPageRespList = new ArrayList<>();
        List<ApiTestCaseStep> apiTestCaseStepList = apiTestCaseStepMapper.findByTestCaseId(testCaseId);
        PageInfo<ApiTestCaseStep> pageInfo = new PageInfo<>(apiTestCaseStepList);
        for (ApiTestCaseStep apiTestCaseStep : apiTestCaseStepList) {
            ApiTestCaseStepPageResp resp = new ApiTestCaseStepPageResp();
            List<TestCaseProcessor> testCaseProcessors = testCaseProcessorMapper.selectByStepId(apiTestCaseStep.getId());
            resp.setTestCaseProcessors(testCaseProcessors);
            BeanUtils.copyProperties(apiTestCaseStep, resp);
            apiTestCaseStepPageRespList.add(resp);
        }
        PageParams pageParams = new PageParams();
        pageParams.setPageNum(pageInfo.getPageNum());
        pageParams.setPages(pageInfo.getPages());
        pageParams.setPageSize(pageInfo.getPageSize());
        pageParams.setPageTotal(pageInfo.getTotal());
        pageParams.setSize(pageInfo.getSize());
        return new PageInfoNew<>(apiTestCaseStepPageRespList, pageParams);
    }

    @Override
    public List<ApiTestCaseStepPageResp> findStepListByTestCaseId(int testCaseId) {
        List<ApiTestCaseStepPageResp> apiTestCaseStepDtoList = new ArrayList<>();
        List<ApiTestCaseStep> apiTestCaseStepList = apiTestCaseStepMapper.findByTestCaseId(testCaseId);
        int envId = apiTestCaseMapper.findById(testCaseId).getEnvId();
        for (ApiTestCaseStep apiTestCaseStep : apiTestCaseStepList) {
            ApiTestCaseStepPageResp apiTestCaseStepPageResp = new ApiTestCaseStepPageResp();
            BeanUtils.copyProperties(apiTestCaseStep, apiTestCaseStepPageResp);
            List<TestCaseProcessor> testCaseProcessors = testCaseProcessorMapper.selectByStepId(apiTestCaseStep.getId());
            apiTestCaseStepPageResp.setEnvId(envId);
            apiTestCaseStepPageResp.setTestCaseProcessors(testCaseProcessors);
            apiTestCaseStepDtoList.add(apiTestCaseStepPageResp);
        }
        return apiTestCaseStepDtoList;
    }


    /**
     * @param testCaseProcessors 处理器列表
     * @param processorEnum      处理器类型
     */
    public void testCaseProcessor(List<TestCaseProcessor> testCaseProcessors, ProcessorEnum processorEnum) {
        if (testCaseProcessors.size() > 0) {
            for (TestCaseProcessor testCaseProcessor : testCaseProcessors) {
                if (ProcessorEnum.valueOfType(testCaseProcessor.getProcessorType()) == processorEnum) {
                    //判断处理器的参数类型（0代表脚本，1代表updateSql）
                    if (null != testCaseProcessor.getContent() && testCaseProcessor.getType() == 1) {
                        dbConnectionService.executeUpdate(testCaseProcessor.getDbConnectionId(), testCaseProcessor.getContent());
                    } else if (null != testCaseProcessor.getContent() && testCaseProcessor.getType() == 0) {
                        //暂时使用groovy脚本-Java 格式
                        GroovyUtils groovyUtils = new GroovyUtils();
                        Map<String, Object> map = new HashMap<>();
                        groovyUtils.groovyRun(testCaseProcessor.getContent(), map);
//                        List<Map<String, String>> mapList = dbConnectionService.executeQuery(testCaseProcessor.getDbConnectionId(), testCaseProcessor.getContent());
                    }
                    // TODO 还有后续逻辑未开发
                }
            }
        }
    }


}
